﻿@page "/"
@using System.Collections
@using System.Diagnostics
@using System.IO.Ports
@using System.Text
@using BlazorSerialUpload.Common
@using BlazorSerialUpload.Models
@using Newtonsoft.Json
@using Timer = System.Timers.Timer;
@inject IMessageService _message
@inject ILogger<Upload> logger;

<PageContainer Title="固件上传">
    <Card>
        <Alert Message="选中需要升级的串口设备"
               Type="success"
               ShowIcon="true"
               Banner
               Style="margin: -12px; margin-bottom: 24px" />
        <Table TItem="PowerBoardEntry"
               Size=@TableSize.Default
               DataSource="Datas"
               HidePagination="true">
            <ChildContent>
                <PropertyColumn Property="c => c.Checked">
                    <Checkbox @bind-Value="@context.Checked"></Checkbox>
                </PropertyColumn>
                <PropertyColumn Property="c => c.UsbLink"></PropertyColumn>
                <PropertyColumn Property="c => c.Ver"></PropertyColumn>
                <PropertyColumn Property="c => c.Progress" Width="50%">
                    <AntDesign.Progress Percent="@context.Progress"></AntDesign.Progress>
                </PropertyColumn>

            </ChildContent>

        </Table>
        <Alert Message="上传固件"
               Type="success"
               ShowIcon="true"
               Banner
               Style="margin: -12px; margin-bottom: 24px;margin-top:24px" />

        <InputFile id="fileInput" OnChange="UploadFiles" hidden multiple />

        <AntDesign.Upload Name="files"
                          FileList="_fileList"
                          Multiple="false"
                          Accept=".bin">
            <label class="ant-btn" for="fileInput">
                <Icon Type="upload" />
                点击上传
            </label>
        </AntDesign.Upload>


        <Alert Message="更新固件"
               Type="success"
               ShowIcon="true"
               Banner
               Style="margin: -12px; margin-bottom: 24px;margin-top:24px" />

        <AntDesign.Button Type="@ButtonType.Primary"
                          Icon="@IconType.Outline.Upload"
                          Loading="@_isLoading"
                          OnClick="UpdateFirmware">
            更新固件
        </AntDesign.Button>

        <AntDesign.Button Type="@ButtonType.Primary"
                          Icon="@IconType.Outline.Reload"
                          OnClick="Reboot">
            重启程序
        </AntDesign.Button>
        <AntDesign.Button Type="@ButtonType.Primary"
                          Icon="@IconType.Outline.Reload"
                          OnClick="Reload">
            复位电源板
        </AntDesign.Button>

        <AntDesign.Button Type="@ButtonType.Primary"
                          Icon="@IconType.Outline.Reload"
                          OnClick="GetVersion">
            获取固件版本
        </AntDesign.Button>
    </Card>

</PageContainer>

@code {

    #region Filed

    private volatile EnTransStatusT _mTransStatus;
    private  uint _flashAddress = 0x1000;
    private static Timer? _timer = new Timer();

    #endregion

    [Parameter]
    public List<PowerBoardEntry> Datas { get; set; } = new List<PowerBoardEntry>();



    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (!firstRender)
        {
            return;
        }

        var jsonFilePath = "/usr/local/etc/fpperf/powerBoard.json";
        var jsonContent = await File.ReadAllTextAsync(jsonFilePath);
        // var jsonContent = "{\"PowerBoard\":[{\"UsbLink\":\"pci-0000_00_14_0-usb-0_6_1_0\",\"SasPcieAddr\":\"0000:65:00.0\"}]}";
        var powerBoard = JsonConvert.DeserializeObject<PowerBoardConfig>(jsonContent);
        if (powerBoard?.PowerBoard != null) Datas = powerBoard.PowerBoard;
        StateHasChanged();
    }




    #region 上传文件

    List<UploadFileItem> _fileList = new List<UploadFileItem>();

    readonly IList<IBrowserFile> _files = new List<IBrowserFile>();
    private void UploadFiles(InputFileChangeEventArgs e)
    {
        foreach (var file in e.GetMultipleFiles())
        {
            _files.Add(file);
        }
        _fileList = _files.Select(file => new UploadFileItem { FileName = file.Name, Size = file.Size }).ToList();

    }



    #endregion

    #region 程序操作

    /// <summary>
    /// 重启程序
    /// </summary>
    private void Reboot()
    {
        var processInfo = new ProcessStartInfo
            {
                FileName = "dotnet",
                Arguments = "BlazorSerialUpload.dll",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                RedirectStandardError = true,
            };

        var process = Process.Start(processInfo);
        process?.WaitForExit();

        // Terminate the current process
        Environment.Exit(0);
    }

    /// <summary>
    /// 复位电源板
    /// </summary>
    /// <returns></returns>
    private async Task Reload()
    {
        foreach (var entry in Datas.Where(c => c.Checked))
        {
            try
            {
                using SerialPort serialPort = new SerialPort($"/dev/{entry.UsbLink}", 115200);
                serialPort.Parity = Parity.None;
                serialPort.DataBits = 8;
                serialPort.StopBits = StopBits.One;
                serialPort.ReadTimeout = 500;
                serialPort.WriteTimeout = 500;

                serialPort.Open();
                byte[] command = [0xFE, 0x08, 0x00, 0x00, 0xEF];
                serialPort.Write(command, 0, command.Length);



                serialPort.Close();
                await _message.Warning($"{entry.UsbLink}复位成功");
            }
            catch (Exception e)
            {

                await _message.Warning(e.Message);
            }
        }
    }

    /// <summary>
    /// 获取版本信息
    /// </summary>
    /// <returns></returns>
    private async Task GetVersion()
    {
        foreach (var entry in Datas.Where(c => c.Checked))
        {
            try
            {
                using SerialPort serialPort = new SerialPort($"/dev/{entry.UsbLink}", 115200);
                serialPort.Parity = Parity.None;
                serialPort.DataBits = 8;
                serialPort.StopBits = StopBits.One;
                serialPort.ReadTimeout = 500;
                serialPort.WriteTimeout = 500;
                serialPort.Open();
                byte[] command = [0xFE, 0x0B, 0x00, 0x00, 0xEF];
                serialPort.Write(command, 0, command.Length);


                // 等待一段时间以确保设备有时间响应
                await Task.Delay(200); // 根据需要调整等待时间

                // 读取返回的信息
                byte[] buffer = new byte[64]; // 定义一个缓冲区
                int bytesRead = serialPort.Read(buffer, 0, buffer.Length);

                // 将读取的数据转换为字符串或其他格式
                byte[] response = new byte[bytesRead];
                Array.Copy(buffer, response, bytesRead);

                // 去掉首尾字节
                if (response.Length > 2) // 确保有足够的字节
                {
                    byte[] trimmedResponse = new byte[response.Length - 2];
                    Array.Copy(response, 1, trimmedResponse, 0, trimmedResponse.Length);

                    // 转换为字符数组
                    char[] chars = Encoding.ASCII.GetChars(trimmedResponse);
                    string result = new string(chars);

                    // 打印返回的信息
                    await InvokeAsync(() =>
                    {

                        entry.Ver = result;
                        StateHasChanged();
                    });
                }
                else
                {

                    await _message.Warning("Received data is too short.");
                }


                serialPort.Close();
              //  await _message.Warning($"{entry.UsbLink}获取版本信息成功");
            }
            catch (Exception e)
            {
                await _message.Warning(e.Message);
            }
        }
    }

    #endregion

    #region 固件升级

    private bool _isLoading;

    private async Task UpdateFirmware()
    {

        if (_files.Count == 0)
        {
            await _message.Warning("请先上传固件");
            return;
        }
        if (Datas.Count(c => c is { Progress: > 0, Checked: true }) > 0)
        {
            await _message.Warning("再次升级请重新加载该页面");
            return;
        }
        if (Datas.Count(c => c.Checked) == 0)
        {
            await _message.Warning("请选中要升级的串口设备");
            return;
        }
        _isLoading = true;

        var filePath = Path.Combine(Directory.GetCurrentDirectory(), "uploads", DateTime.Now.ToString("yyyyMMddhhmmss") + ".bin");

        // Create uploads directory if it doesn't exist
        if (!Directory.Exists(Path.Combine(Directory.GetCurrentDirectory(), "uploads")))
        {
            Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), "uploads"));
        }

        var file = _files[0];

        var buffer = new byte[file.Size];
        var s = await file.OpenReadStream().ReadAsync(buffer);
        await using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        {
            await fileStream.WriteAsync(buffer);
            await fileStream.FlushAsync();
        };

        //处理
        await DoUpgrade(filePath);


        File.Delete(filePath);
        _isLoading = false;
    }

    #endregion







    #region UratUtil

    public async Task DoUpgrade(string filePath)
    {
        try
        {

            foreach (var entry in Datas.Where(c => c.Checked))
            {
                // 从 JSON 中提取 UsbLink 值并通过串口发送
                // using SerialPort serialPort = new SerialPort($"COM4", 115200);
                using SerialPort serialPort = new SerialPort($"/dev/{entry.UsbLink}", 115200);

                try
                {
                    byte transNumber = 1;
                    byte[] frameData = new byte[530];
                    bool threadFlag = true;
                    _mTransStatus = EnTransStatusT.TRANS_IDLE;


                    serialPort.Parity = Parity.None;
                    serialPort.DataBits = 8;
                    serialPort.StopBits = StopBits.One;
                    serialPort.ReadTimeout = 500;
                    serialPort.WriteTimeout = 500;
                    serialPort.DataReceived += (sender, e) =>
                    {
                        SerialPort sp = (SerialPort)sender;
                        int num1 = 0;
                        int num2 = 530;
                        byte[] numArray = new byte[num2];
                        byte[] numArray1 = new byte[num2];
                        int bytesToRead = sp.BytesToRead;
                        if (bytesToRead > num2)
                        {
                            sp.Read(numArray, 0, num2);
                            return;
                        }

                        int num4 = 5;
                        while (num4 > 0)
                        {
                            var num = (bytesToRead <= 0 ? 0 :sp.Read(numArray, 0, bytesToRead));
                            if (num <= 0)
                            {
                                num4--;
                                Thread.Sleep(50);
                            }
                            else
                            {
                                if (bytesToRead + num1 > num2)
                                {
                                    return;
                                }

                                Buffer.BlockCopy(numArray, 0, numArray1, num1, bytesToRead);
                                num1 += bytesToRead;
                                num4 = 5;
                            }

                            bytesToRead = sp.BytesToRead;
                        }

                        if (num1 != 0 && 44141 == numArray1[0] + (numArray1[1] << 8) && numArray1[2] == (numArray1[3] ^ 255))
                        {
                            var num3 = numArray1[4] + (numArray1[5] << 8);
                            if (num3 >= 10 && num3 <= 522 && (ushort)(numArray1[6 + num3] + (numArray1[6 + num3 + 1] << 8)) == Cal_CRC16(numArray1, 6, (uint)num3))
                            {
                                transNumber = (byte)(transNumber + 1);
                                if (transNumber == 0)
                                {
                                    transNumber = 1;
                                }

                                Buffer.BlockCopy(numArray1, 0, frameData, 0, num1 - 2);
                                EnPacketStatusT enPacketStatusT = (EnPacketStatusT)frameData[7];
                                if (_mTransStatus == EnTransStatusT.TRANS_BEGIN)
                                {
                                    StopCommTimer();
                                    EnTransStatusT enTransStatusT;
                                    switch (enPacketStatusT)
                                    {
                                        case EnPacketStatusT.PACKET_ACK_OK:
                                            {
                                                enTransStatusT = EnTransStatusT.TRANS_FINISHED;
                                                break;
                                            }
                                        case EnPacketStatusT.PACKET_ACK_ERROR:
                                            {
                                                enTransStatusT = EnTransStatusT.TRANS_FAILED;
                                                break;
                                            }
                                        case EnPacketStatusT.PACKET_ACK_ABORT:
                                        case EnPacketStatusT.PACKET_ACK_TIMEOUT:
                                            {
                                                enTransStatusT = EnTransStatusT.TRANS_FAILED;
                                                break;
                                            }
                                        case EnPacketStatusT.PACKET_ACK_ADDR_ERROR:
                                            {
                                                enTransStatusT = EnTransStatusT.TRANS_ADDR_ERROR;
                                                break;
                                            }
                                        default:
                                            {
                                                goto case EnPacketStatusT.PACKET_ACK_TIMEOUT;
                                            }
                                    }
                                    _mTransStatus = enTransStatusT;
                                }
                            }
                        }
                    };
                    serialPort.Open();

                    uint mAppFlashAddr = _flashAddress;
                    EnTransStatusT mTransStatus = EnTransStatusT.TRANS_IDLE;
                    byte[] numArray = null;
                    int length = 0;
                    int num = 0;
                    int num1 = 0;
                    byte[] numArray1 = new byte[512];
                    int num2 = 0;
                    int num3 = 0;
                    int num4 = filePath.LastIndexOf(".", StringComparison.Ordinal);
                    string str = filePath.Substring(num4, filePath.Length - num4);
                    if (str == ".bin")
                    {
                        FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                        length = (int)fileStream.Length;
                        numArray = new byte[length];
                        fileStream.Read(numArray, 0, numArray.Length);
                        fileStream.Close();
                    }
                    else if (str == ".hex")
                    {
                        uint num5 = 0;
                        if (HexToBin.ExecResult.ExecOk == (new HexToBin()).HEX_ConvertBin(filePath, ref num5, ref numArray))
                        {
                            length = numArray.Length;
                        }
                    }
                    else if (str == ".srec")
                    {
                        uint num6 = 0;
                        if (HexToBin.ExecResult.ExecOk == (new HexToBin()).SREC_ConvertBin(filePath, ref num6, ref numArray))
                        {
                            length = numArray.Length;
                        }
                    }

                    if (length != 0)
                    {
                        num1 = length;
                        num2 = length / 512;
                        if (length % 512 != 0)
                        {
                            num2++;
                        }
                    }
                    else
                    {
                        threadFlag = false;
                        mTransStatus = EnTransStatusT.TRANS_FILE_INVALID;
                    }

                    EnPacketCmdT enPacketCmdT = EnPacketCmdT.PACKET_CMD_APP_UPGRADE;
                    await CommProgress(100, 0, entry.UsbLink);
                    do
                    {
                        if (!threadFlag)
                        {
                            break;
                        }

                        var flag = false;
                        switch (enPacketCmdT)
                        {
                            case EnPacketCmdT.PACKET_CMD_HANDSHAKE:
                                {
                                    //  flag = await CommModemPackage(32, 17, 0, null, 0, 1000);
                                    var tuple = CommModemPackage(32, 17, 0, null, 0, transNumber);
                                    Array.Clear(frameData, 0, frameData.Length);
                                    StartCommTimer(1000);
                                    flag = SerialSendData(tuple.Item1, tuple.Item2, serialPort);
                                   
                                    if (!flag)
                                    {
                                        _mTransStatus = EnTransStatusT.TRANS_FAILED;
                                        StopCommTimer();
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    while (_mTransStatus == EnTransStatusT.TRANS_BEGIN)
                                    {
                                    }

                                    if (_mTransStatus != EnTransStatusT.TRANS_FINISHED)
                                    {
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    enPacketCmdT = EnPacketCmdT.PACKET_CMD_ERASE_FLASH;
                                    goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                }
                            case EnPacketCmdT.PACKET_CMD_JUMP_TO_APP:
                                {
                                    // flag = await CommModemPackage(33, 17, 0, null, 0, 1000);
                                    var tuple = CommModemPackage(33, 17, 0, null, 0, transNumber);
                                    Array.Clear(frameData, 0, frameData.Length);
                                    StartCommTimer(1000);
                                    flag = SerialSendData(tuple.Item1, tuple.Item2, serialPort);
                                   
                                    if (!flag)
                                    {
                                        _mTransStatus = EnTransStatusT.TRANS_FAILED;
                                        StopCommTimer();
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    while (_mTransStatus == EnTransStatusT.TRANS_BEGIN)
                                    {
                                    }

                                    if (_mTransStatus != EnTransStatusT.TRANS_FINISHED)
                                    {
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    await CommProgress(num2, num2, entry.UsbLink);
                                    mTransStatus = EnTransStatusT.TRANS_FINISHED;
                                    goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                }
                            case EnPacketCmdT.PACKET_CMD_APP_DOWNLOAD:
                                {
                                    if (length <= 512)
                                    {
                                        Buffer.BlockCopy(numArray, num, numArray1, 0, length);
                                        // flag = await CommModemPackage(34, 18, mAppFlashAddr, numArray1, (ushort)length, 2000);
                                        var tuple = CommModemPackage(34, 18, mAppFlashAddr, numArray1, (ushort)length, transNumber);
                                        Array.Clear(frameData, 0, frameData.Length);
                                        StartCommTimer(2000);
                                        flag = SerialSendData(tuple.Item1, tuple.Item2, serialPort);
                                       
                                    }
                                    else
                                    {
                                        Buffer.BlockCopy(numArray, num, numArray1, 0, 512);
                                        // flag = await CommModemPackage(34, 18, mAppFlashAddr, numArray1, 512, 2000);
                                        var tuple = CommModemPackage(34, 18, mAppFlashAddr, numArray1, 512, transNumber);
                                        Array.Clear(frameData, 0, frameData.Length);
                                        StartCommTimer(2000);
                                        flag = SerialSendData(tuple.Item1, tuple.Item2, serialPort);
                                     
                                    }

                                    if (!flag)
                                    {
                                        _mTransStatus = EnTransStatusT.TRANS_FAILED;
                                        StopCommTimer();
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    while (_mTransStatus == EnTransStatusT.TRANS_BEGIN)
                                    {
                                    }

                                    if (_mTransStatus != EnTransStatusT.TRANS_FINISHED)
                                    {
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    if (length <= 512)
                                    {
                                        length = 0;
                                        enPacketCmdT = EnPacketCmdT.PACKET_CMD_FLASH_CRC;
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    num += 512;
                                    length -= 512;
                                    mAppFlashAddr += 512;
                                    num3++;
                                    await CommProgress(num2, num3, entry.UsbLink);
                                    goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                }
                            case EnPacketCmdT.PACKET_CMD_APP_UPLOAD:
                                {
                                    if (_mTransStatus != EnTransStatusT.TRANS_TIMEOUT && _mTransStatus != EnTransStatusT.TRANS_FAILED && _mTransStatus != EnTransStatusT.TRANS_ABORT && _mTransStatus != EnTransStatusT.TRANS_ADDR_ERROR)
                                    {
                                        continue;
                                    }

                                    mTransStatus = _mTransStatus;
                                    break;
                                }
                            case EnPacketCmdT.PACKET_CMD_ERASE_FLASH:
                                {
                                    numArray1[0] = (byte)(num1 & 255);
                                    numArray1[1] = (byte)(num1 >> 8 & 255);
                                    numArray1[2] = (byte)(num1 >> 16 & 255);
                                    numArray1[3] = (byte)(num1 >> 24 & 255);
                                    //  flag = await CommModemPackage(36, 18, mAppFlashAddr, numArray1, 4, 5000);
                                    var tuple = CommModemPackage(36, 18, mAppFlashAddr, numArray1, 4, transNumber);
                                    Array.Clear(frameData, 0, frameData.Length);
                                    StartCommTimer(5000);
                                    flag = SerialSendData(tuple.Item1, tuple.Item2, serialPort);
                                  
                                    if (!flag)
                                    {
                                        _mTransStatus = EnTransStatusT.TRANS_FAILED;
                                        StopCommTimer();
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    while (_mTransStatus == EnTransStatusT.TRANS_BEGIN)
                                    {
                                    }

                                    if (_mTransStatus != EnTransStatusT.TRANS_FINISHED)
                                    {
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    enPacketCmdT = EnPacketCmdT.PACKET_CMD_APP_DOWNLOAD;
                                    num3 = 0;
                                    num = 0;
                                    goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                }
                            case EnPacketCmdT.PACKET_CMD_FLASH_CRC:
                                {
                                    numArray1[0] = (byte)(num1 & 255);
                                    numArray1[1] = (byte)(num1 >> 8 & 255);
                                    numArray1[2] = (byte)(num1 >> 16 & 255);
                                    numArray1[3] = (byte)(num1 >> 24 & 255);
                                    // flag = await CommModemPackage(37, 18, _mAppFlashAddr, numArray1, 4, 3000);
                                    var tuple = CommModemPackage(37, 18, _flashAddress, numArray1, 4, transNumber);
                                    Array.Clear(frameData, 0, frameData.Length);
                                    StartCommTimer(3000);
                                    flag = SerialSendData(tuple.Item1, tuple.Item2, serialPort);
                                  
                                    if (!flag)
                                    {
                                        _mTransStatus = EnTransStatusT.TRANS_FAILED;
                                        StopCommTimer();
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    while (_mTransStatus == EnTransStatusT.TRANS_BEGIN)
                                    {
                                    }

                                    if (_mTransStatus != EnTransStatusT.TRANS_FINISHED)
                                    {
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    if ((ushort)(frameData[16] + (frameData[17] << 8)) != Cal_CRC16(numArray, 0, (uint)num1))
                                    {
                                        _mTransStatus = EnTransStatusT.TRANS_FAILED;
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    enPacketCmdT = EnPacketCmdT.PACKET_CMD_JUMP_TO_APP;
                                    goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                }
                            case EnPacketCmdT.PACKET_CMD_APP_UPGRADE:
                                {
                                    // flag = await CommModemPackage(38, 17, 0, null, 0, 1000);
                                    var tuple = CommModemPackage(38, 17, 0, null, 0, transNumber);
                                    Array.Clear(frameData, 0, frameData.Length);
                                    StartCommTimer(1000);
                                    flag = SerialSendData(tuple.Item1, tuple.Item2, serialPort);
                                 
                                    if (!flag)
                                    {
                                        _mTransStatus = EnTransStatusT.TRANS_FAILED;
                                        StopCommTimer();
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    while (_mTransStatus == EnTransStatusT.TRANS_BEGIN)
                                    {
                                    }

                                    if (_mTransStatus != EnTransStatusT.TRANS_FINISHED)
                                    {
                                        goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                    }

                                    enPacketCmdT = EnPacketCmdT.PACKET_CMD_HANDSHAKE;
                                    Thread.Sleep(200);
                                    goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                }
                            default:
                                {
                                    goto case EnPacketCmdT.PACKET_CMD_APP_UPLOAD;
                                }
                        }
                    } while (mTransStatus != EnTransStatusT.TRANS_FINISHED);

                    StopCommTimer();
                    serialPort.Close();
                    var message = CommThreadFinish(EnThreadNumberT.TRANS_FILE_THEAD, mTransStatus, enPacketCmdT);
                    await _message.Warning(message);
                }
                catch (Exception e)
                {

                    logger.LogError(e.ToString(), e.Message);
                    await _message.Warning(e.Message);
                }
                finally
                {
                    serialPort.Close();
                }


            }

        }
        catch (Exception ex)
        {
            var message = $"Error sending data: {ex.Message}";
            await _message.Warning(message);
            logger.LogError(ex.ToString(), ex.Message);
        }

    }


    public string CommThreadFinish(EnThreadNumberT threadNum, EnTransStatusT threadSta, EnPacketCmdT threadCmd)
    {

        string? str = null;
        string? str1 = null;

        if (threadNum == EnThreadNumberT.TRANS_FILE_THEAD)
        {
            str = "更新固件";
        }
        else if (threadNum == EnThreadNumberT.RECV_FILE_THEAD)
        {
            str = "上传";
        }
        switch (threadCmd)
        {
            case EnPacketCmdT.PACKET_CMD_HANDSHAKE:
                {
                    str1 = "握手";
                    break;
                }
            case EnPacketCmdT.PACKET_CMD_JUMP_TO_APP:
                {
                    str1 = "跳转";
                    break;
                }
            case EnPacketCmdT.PACKET_CMD_APP_DOWNLOAD:
                {
                    str1 = "更新固件";
                    break;
                }
            case EnPacketCmdT.PACKET_CMD_APP_UPLOAD:
                {
                    str1 = "上传";
                    break;
                }
            case EnPacketCmdT.PACKET_CMD_ERASE_FLASH:
                {
                    str1 = "擦除Flash";
                    break;
                }
            case EnPacketCmdT.PACKET_CMD_FLASH_CRC:
                {
                    str1 = "Flash校验";
                    break;
                }
            case EnPacketCmdT.PACKET_CMD_APP_UPGRADE:
                {
                    str1 = "APP升级";
                    break;
                }
        }
        switch (threadSta)
        {
            case EnTransStatusT.TRANS_TIMEOUT:
                {
                    return string.Concat(str, "程序,", str1, "超时,请检查设备及连接线是否正常!");

                }
            case EnTransStatusT.TRANS_FINISHED:
                {
                    return string.Concat(str, "完成！");

                }
            case EnTransStatusT.TRANS_FAILED:
                {
                    return string.Concat(str, "程序,", str1, "失败请检查参数是否合法!");

                }
            case EnTransStatusT.TRANS_ABORT:
                {
                    return string.Concat(str, "程序,终止!");

                }
            case EnTransStatusT.TRANS_ADDR_ERROR:
                {
                    return string.Concat(str, "程序,", str1, "地址错误请输入有效地址值!");

                }
            case EnTransStatusT.TRANS_FILE_INVALID:
                {
                    return string.Concat(str, "程序,请选择有效的文件!");

                }
            default:
                {
                    return "";
                }
        }
    }


    #endregion



    #region Timer


    private void StopCommTimer()
    {
        if (_timer != null)
        {
            _timer.Enabled = false;
            _timer.Stop();
        }
    }


    private void StartCommTimer(ushort value)
    {

        // 创建并启动定时器
        _timer = new Timer(value);
        _timer.Elapsed += (s, e) =>
        {
            if (_mTransStatus == EnTransStatusT.TRANS_BEGIN)
            {
                _mTransStatus = EnTransStatusT.TRANS_TIMEOUT;
            }
        };
        _timer.Enabled = true;
        _timer.AutoReset = false; // 不重复
        _timer.Start();
    }

    #endregion


    #region 通用方法

    public async Task CommProgress(int total, int currVal, string com)
    {
        await InvokeAsync(() =>
        {

            var num = (int)(currVal / (float)total * 100f);
            foreach (var item in Datas)
            {
                if (item.UsbLink == com)
                {
                    item.Progress = num;
                    break;
                }
            }
            StateHasChanged();
        });

    }

    // private async Task<bool> CommModemPackage(byte cmd, byte type, uint addr, byte[] data, ushort length, ushort timeout)
    private Tuple<byte[], ushort> CommModemPackage(byte cmd, byte type, uint addr, byte[] data, ushort length, byte transNumber)
    {
        byte[] mTransNumber = new byte[530];
        ushort num = 44141;
        ushort num1 = 6;
        ushort num2 = 10;
        ushort num3 = (ushort)(num2 + num1);
        ushort num4 = (ushort)(length + num2);
        ushort num5 = 0;
        ushort num6 = num5;
        num5 = (ushort)(num6 + 1);
        mTransNumber[num6] = (byte)(num & 255);
        ushort num7 = num5;
        num5 = (ushort)(num7 + 1);
        mTransNumber[num7] = (byte)(num >> 8 & 255);
        ushort num8 = num5;
        num5 = (ushort)(num8 + 1);
        mTransNumber[num8] = transNumber;
        ushort num9 = num5;
        num5 = (ushort)(num9 + 1);
        mTransNumber[num9] = (byte)(transNumber ^ 255);
        ushort num10 = num5;
        num5 = (ushort)(num10 + 1);
        mTransNumber[num10] = (byte)(num4 & 255);
        ushort num11 = num5;
        num5 = (ushort)(num11 + 1);
        mTransNumber[num11] = (byte)(num4 >> 8);
        ushort num12 = num5;
        num5 = (ushort)(num12 + 1);
        mTransNumber[num12] = cmd;
        ushort num13 = num5;
        num5 = (ushort)(num13 + 1);
        mTransNumber[num13] = type;
        ushort num14 = num5;
        num5 = (ushort)(num14 + 1);
        mTransNumber[num14] = (byte)(addr & 255);
        ushort num15 = num5;
        num5 = (ushort)(num15 + 1);
        mTransNumber[num15] = (byte)(addr >> 8 & 255);
        ushort num16 = num5;
        num5 = (ushort)(num16 + 1);
        mTransNumber[num16] = (byte)(addr >> 16 & 255);
        ushort num17 = num5;
        num5 = (ushort)(num17 + 1);
        mTransNumber[num17] = (byte)(addr >> 24 & 255);
        for (int i = num5; i < num3; i++)
        {
            mTransNumber[i] = 0;
        }
        num5 = num3;
        if (length != 0)
        {
            Buffer.BlockCopy(data, 0, mTransNumber, num5, length);
        }
        num5 = (ushort)(num5 + length);
        ushort num18 = Cal_CRC16(mTransNumber, num1, num4);
        ushort num19 = num5;
        num5 = (ushort)(num19 + 1);
        mTransNumber[num19] = (byte)(num18 & 255);
        ushort num20 = num5;
        num5 = (ushort)(num20 + 1);
        mTransNumber[num20] = (byte)(num18 >> 8);
        // Array.Clear(_mCommRecvData, 0, _mCommRecvData.Length);
        //return await CommModemSendData(mTransNumber, num5, timeout);
        return new Tuple<byte[], ushort>(mTransNumber, num5);
    }

    /// <summary>
    /// 串口传输数据
    /// </summary>
    /// <param name="transStr"></param>
    /// <param name="length"></param>
    /// <param name="comPort"></param>
    /// <returns></returns>
    private bool SerialSendData(byte[] transStr, ushort length, SerialPort comPort)
    {
        bool flag;

        try
        {
            comPort.Write(transStr, 0, length);
            _mTransStatus = EnTransStatusT.TRANS_BEGIN;
            return true;
        }
        catch (Exception exception)
        {
            logger.LogError(exception, exception.Message);
            flag = false;
        }
        return flag;
    }




    private ushort Cal_CRC16(byte[] pData, int offset, uint size)
    {
        ushort calCrc16 = 41612;
        uint num = (uint)offset;
        while (size != 0)
        {
            uint num1 = num;
            num = num1 + 1;
            calCrc16 = (ushort)(calCrc16 ^ pData[num1]);
            for (byte i = 0; i < 8; i = (byte)(i + 1))
            {
                if ((calCrc16 & 1) != 1)
                {
                    calCrc16 = (ushort)(calCrc16 >> 1);
                }
                else
                {
                    calCrc16 = (ushort)(calCrc16 >> 1);
                    calCrc16 = (ushort)(calCrc16 ^ 33800);
                }
            }
            size--;
        }
        calCrc16 = (ushort)(~calCrc16);
        return calCrc16;
    }

    #endregion


    #region 公共字段

    public class CustomComparer : IComparer
    {
        public int Compare(object x, object y)
        {
            string str = (string)x;
            string str1 = (string)y;
            if (str.Length > str1.Length)
            {
                return 1;
            }
            if (str.Length < str1.Length)
            {
                return -1;
            }
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] > str1[i])
                {
                    return 1;
                }
                if (str[i] < str1[i])
                {
                    return -1;
                }
            }
            return 0;
        }
    }

    public enum EnPacketCmdT
    {
        PACKET_CMD_HANDSHAKE = 32,
        PACKET_CMD_JUMP_TO_APP = 33,
        PACKET_CMD_APP_DOWNLOAD = 34,
        PACKET_CMD_APP_UPLOAD = 35,
        PACKET_CMD_ERASE_FLASH = 36,
        PACKET_CMD_FLASH_CRC = 37,
        PACKET_CMD_APP_UPGRADE = 38
    }

    public enum EnPacketStatusT
    {
        PACKET_ACK_OK,
        PACKET_ACK_ERROR,
        PACKET_ACK_ABORT,
        PACKET_ACK_TIMEOUT,
        PACKET_ACK_ADDR_ERROR
    }

    public enum EnThreadNumberT
    {
        TRANS_FILE_THEAD = 1,
        RECV_FILE_THEAD = 2
    }

    public enum EnTransStatusT
    {
        TRANS_IDLE,
        TRANS_BEGIN,
        TRANS_TIMEOUT,
        TRANS_FINISHED,
        TRANS_FAILED,
        TRANS_ABORT,
        TRANS_ADDR_ERROR,
        TRANS_FILE_INVALID
    }

    #endregion
}
